package com.qianniu.napi.admin.web;

import akka.actor.ActorRef;
import akka.actor.Props;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.google.common.base.Strings;
import com.qianniu.napi.admin.entity.*;
import com.qianniu.napi.admin.entity.penum.FantimeType;
import com.qianniu.napi.admin.entity.penum.GtypeEnum;
import com.qianniu.napi.admin.entity.penum.RefundEnum;
import com.qianniu.napi.admin.entity.penum.StatusEnum;
import com.qianniu.napi.admin.service.*;
import com.qianniu.napi.admin.service.akka.AkkaServer;
import com.qianniu.napi.admin.service.akka.OrderActor;
import com.qianniu.napi.common.config.Constants;
import com.qianniu.napi.common.util.ObjectUtil;
import com.qianniu.napi.common.util.StringUtil;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.Valid;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 订单
 * </p>
 *
 * @author chenxuebin
 * @since 2018-06-24
 */
@Controller
public class OrderController {

    private static final Logger logger = LoggerFactory.getLogger(OrderController.class);

    @Autowired
    private IGoodsService goodsService;
    @Autowired
    private IGoodsSkuService goodsSkuService;
    @Autowired
    private IOrderService orderService;
    @Autowired
    private IAddressService addressService;
    @Autowired
    private IQnpay qnpay;
    @Autowired
    private IMerchantConfigService merchantConfigService;
    @Autowired
    private IOrderGoodsService orderGoodsService;
    @Autowired
    private IAccountService accountService;
    @Autowired
    private IAccountFlowService accountflowService;
    @Autowired
    private IMaccountService maccountService;
    @Autowired
    private IMaccountFlowService maccountFlowService;
    @Autowired
    private IPintuanOpenService pintuanOpenService;
    @Autowired
    private IPintuanLogService pintuanLogService;
    @Autowired
    private ICouponService couponService;
    @Autowired
    private IJifenFlowService jifenFlowService;
    @Autowired
    private IJifenService jifenService;
    @Autowired
    private IOrderExtService orderExtService;
    @Autowired
    private IRedisService redisService;
    @Autowired
    private IUserService userService;
    @Autowired
    private IHexiaoLogService hexiaoService;
    @Autowired
    private IStoreService storeService;
    @Autowired
    private IOrderRefundService refundService;
    @Autowired
    private IConfigService configService;
    @Autowired
    private IOrderRefundService orderRefundService;

    @RequiresPermissions("admin:user:view")
    @RequestMapping("admin/order/index")
    public String index(Model model) {

        model.addAttribute("isAdmin", ObjectUtil.getIsAdmin());
        Wrapper<Config> cwrapper = new EntityWrapper<Config>()
                .setSqlSelect("code,name")
                .eq("level", 1);
        MerchantApp mapp = redisService.getMApp(ObjectUtil.getMpid());
        cwrapper.eq("mpid", mapp.getId());
        cwrapper.eq("type", "kuaidi").orderBy("");

        List<Config> kuaidis = configService.selectList(cwrapper);

        model.addAttribute("kuaidis", kuaidis);
        return "admin/order";
    }

    @RequiresPermissions("admin:user:view")
    @RequestMapping("/admin/order/list")
    @ResponseBody
    public Page<Order> alist(@RequestParam(value = "offset", required = false) Integer offset,
                             @RequestParam(value = "status", required = false) Integer status,
                             @RequestParam(value = "type", required = false) Integer type,
                             @RequestParam(value = "search", required = false) String search,
                             @RequestParam(value = "limit", required = false) Integer limit) {
        Wrapper<Order> wrapper = new EntityWrapper<Order>();
        int utype = ObjectUtil.getUserType();
        Long sid = ObjectUtil.getSid();
        if (utype == 99) wrapper.eq("mid", ObjectUtil.getMid());
        else if(sid != null && sid > 0) wrapper.eq("sid", sid);
        else wrapper.eq("mpid", ObjectUtil.getMpid());

        wrapper.eq("state", 1);
        wrapper.ge("gtype", 1);
        wrapper.le("gtype", 4);
        if (type != null) wrapper.le("type", type);
        logger.debug("==============================status=" + status);
        logger.debug("==============================search=" + search);
        if (status != null && status != 99) wrapper.eq("status", status);
        if (!Strings.isNullOrEmpty(search))
            wrapper.andNew().like("order_no", search).or().like("remark", search).or().like("service_code", search)
                    .or().like("address", search).or().like("linkman", search).or().like("phone", search);

        wrapper.orderBy("id", false);
        Page<Order> page = orderService.selectPage(new Page<Order>(offset / limit + 1, limit), wrapper);

        return page;
    }

    @RequestMapping("/admin/order/add")
    public String add(@Valid Order bean, BindingResult bindingResult) {
        // 字段校验
        if (bindingResult.hasErrors()) {
            logger.debug("There are errors! {}", bindingResult);
            return null;
        }
        bean.setCreatetime(new Date());
        bean.setMid(ObjectUtil.getMid());
        bean.setUid(ObjectUtil.getUid());
        bean.insert();
        return "admin/order";
    }

    @RequestMapping("/admin/order/getOrderById")
    @ResponseBody
    public Order getOrderById(long id) {
        Order order = orderService.selectById(id);
        return order;
    }

    @RequestMapping("/admin/order/deleteOne")
    @ResponseBody
    public int deleteOne(long id) {
        boolean isSucc = orderService.deleteById(id);
        return isSucc ? 1 : 0;
    }

    @RequestMapping("/admin/order/changeState")
    @ResponseBody
    public String changeState(long id, int state) {
        Order bean = new Order();
        bean.setId(id);
        bean.setState(state);
        bean.setModifytime(new Date());
        bean.setModifier(ObjectUtil.getUid());
        orderService.updateById(bean);
        return "success";
    }

    @RequestMapping("/admin/order/fahuo")
    @ResponseBody
    public Jinfo fahuo(Order order) {
        Jinfo jinfo = new Jinfo();
        logger.debug("----------------fahuo order=" + JSON.toJSONString(order));

        //如果是商家发货
        if (order.getShipperMethod() != null && order.getShipperMethod() == 3) {

            // 领取货之后返自购奖励
            // ===待完善===
            AkkaServer.system.actorOf(Props.create(OrderActor.class))
                    .tell(Constants.AKKA_MSG_ORDER_ZIGOUFAN + "@" + order.getId() + "@" + FantimeType.afterhexiao.getVal(), ActorRef.noSender());

            // ===商家入账处理
            if (order.getSid() != null && order.getSid().longValue() > 0) {
                AkkaServer.system.actorOf(Props.create(OrderActor.class))
                        .tell(Constants.AKKA_MSG_ORDER_STORE_PAY + "@" + order.getId(), ActorRef.noSender());
            }

            //领取货之后分销结算，触发时机：扫码核销确认收货【+点击确认收货】
            //商品分享直推奖励
            logger.info("---------------------------------------------------hxok order.getSharefan()=" + order.getSharefan());
            logger.info("---------------------------------------------------hxok order.getFantimeType()=" + order.getFantimeType());
            if (order.getSharefan() != null && order.getSharefan().doubleValue() > 0
                    && order.getFantimeType() == FantimeType.afterhexiao.getVal()) {
                AkkaServer.system.actorOf(Props.create(OrderActor.class))
                        .tell(Constants.AKKA_MSG_ORDER_SHAREFAN + "@" + order.getId(), ActorRef.noSender());
            }

            if (order.getSid() != null) {
                // 商家核销+1
                Store store = storeService.selectOne(new EntityWrapper<Store>()
                        .setSqlSelect("id,zhexiao,jrhexiao,xdhexiao,renqi").eq("id", order.getSid()));
                if (store != null) {
                    store.setZhexiao(store.getZhexiao() + 1);
                    store.setJrhexiao(store.getJrhexiao() + 1);
                    store.setRenqi(store.getRenqi() + 10);
                    store.setModifytime(new Date());
                    store.setModifier(ObjectUtil.getUid());
                    store.updateById();
                }
            }
        }
//        Order dorder = orderService.selectById(order.getId());
//        MerchantConfig mconfig = redisService.getMconfig(dorder.getMpid());

        OrderGoods og = new OrderGoods();
        og.setOid(order.getId());
        og.setStatus(order.getStatus());
        order.setStatus(StatusEnum.receving.getVal());
        og.setStatus(StatusEnum.receving.getVal());

        og.setModifytime(new Date());
        og.setModifier(ObjectUtil.getUid());
        orderGoodsService.update(og, new EntityWrapper<OrderGoods>().eq("oid", order.getId()));

        order.setConfirmtime(new Date());

        order.setModifytime(new Date());
        order.setModifier(ObjectUtil.getUid());
        order.updateById();
        return jinfo;
    }

    @RequestMapping("/admin/order/changeStatus")
    @ResponseBody
    public Jinfo changeStatus(long id, int status) {
        Jinfo json = new Jinfo();
        Order order = orderService.selectById(id);
        if (order == null) {
            json.setCode(4);
            return json;
        }
        int oldStatus = order.getStatus();
//        Map map = new HashMap<String,Object>();
        Map map = null;
        if (Strings.isNullOrEmpty(order.getRefundNo())) {
            order.setRefundNo(StringUtil.getRefundNo());
            order.setIsRefund(1);
        }
        if (oldStatus == StatusEnum.forsend.getVal() && order.getRealpay().doubleValue() > 0) {
            // 退款
            map = qnpay.cancelOrder(order, ObjectUtil.getAppid());
        }
        if (map == null || !map.containsKey("result_code") || !map.get("result_code").equals("SUCCESS")) {
            json.setCode(5);//
            json.setInfo("weixin refund error=" + map == null ? "" : JSON.toJSONString(map));//
            return json;
        }

        order.setState(status);
        order.setModifytime(new Date());
        order.setModifier(ObjectUtil.getUid());
        orderService.updateById(order);

        return json;
    }

    //1、卖货类型的订单支持取消
    //2、订单取消只限在核销前或者用户确认收货前
    //3、一旦核销或者确认收货，不在之前该接口取消订单，仅支持线下退货线下退款
    @RequestMapping("/admin/order/cancel")
    @ResponseBody
    public Jinfo cancelOrder(@RequestParam("oid") Long oid) {
        Jinfo json = new Jinfo();
        Map<String, Object> map = null;
        if (oid == null) {
            json.setCode(1);
            json.setMsg("请求参数错误");
            return json;
        }
        Order order = orderService.selectById(oid);
        if (order == null) {
            json.setCode(4);
            json.setMsg("该订单不存在");
            return json;
        }
        // 商家秒退
        if (order.getStatus() < 1 || order.getStatus() > 3) {
            json.setCode(1);
            json.setMsg("当前不支持取消订单操作");
            return json;
        }
        //订单状态@-1：已取消；0：已关闭；1：待支付；2：待发货；3：待收货；4：待评论；5：已完成
        if (Strings.isNullOrEmpty(order.getRefundNo())) {
            order.setRefundNo(StringUtil.getSnNo("R"));
            order.setStatus(-1);
            order.setIsRefund(1);
        }

        OrderRefund or = orderRefundService.selectOne(new EntityWrapper<OrderRefund>()
                .eq("order_no", order.getOrderNo()));
        if (or != null) {
            or.setApplynum(or.getApplynum() + 1);
            or.setModifier(ObjectUtil.getUid());
            or.setModifytime(new Date());
            or.updateById();
            return json;
        }

        // 生成订单取消申请
        or = new OrderRefund();
        or.setRealpay(order.getRealpay());
        or.setRefund(order.getRealpay());
        or.setOid(order.getId());
        or.setApplynum(1);
        or.setOrderNo(order.getOrderNo());
        or.setRefundNo(order.getRefundNo());
        or.setGoodsName(order.getGoodsName());
        or.setRemark("商家取消订单");
        or.setStatus(RefundEnum.success.getVal());// 默认受理中
        or.setState(1);

        String ip = ObjectUtil.getIP();
        or.setIp(ip);// 默认受理中

        or.setUid(ObjectUtil.getUid());
        or.setMid(ObjectUtil.getMid());
        or.setMpid(ObjectUtil.getMpid());
        or.setCreatetime(new Date());
        or.insert();

        order.updateById();

        OrderGoods og = new OrderGoods();
        og.setStatus(-1);
        og.setOid(order.getId());
        orderGoodsService.update(og, new EntityWrapper<OrderGoods>().eq("oid", order.getId()));

        //直接退款，需要满足
        //如果是实物商品，需要发货，待发货（未发货）可以直接退款
        //如果是非物商品，待收货待服务（不需发货），还未核销可以直接退款
        //核销之后不退
        if ((order.getGtype() == GtypeEnum.real.getVal() && order.getStatus() <= StatusEnum.forsend.getVal()) ||
                (order.getGtype() > GtypeEnum.real.getVal() && order.getGtype() <= GtypeEnum.shangmen.getVal() && order.getStatus() <= StatusEnum.receving.getVal())
                ) {
            // 退现金
            if (order.getRealpay().doubleValue() > 0) {
                map = qnpay.cancelOrder(order, ObjectUtil.getAppid());
                if (map != null && map.containsKey("code")) {
                    json.setCode(Integer.valueOf(map.get("code").toString()));
                    json.setMsg(map.get("msg").toString());
                }
                if (map != null && map.containsKey("return_code") && map.containsKey("result_code")
                        && map.get("return_code").toString().equals("SUCCESS") && map.get("result_code").toString().equals("SUCCESS")) {
                    // 更新订单+订单商品状态：已取消
                    order.setStatus(StatusEnum.cancel.getVal());
                    order.setIsRefund(1);
                    order.updateById();

                    or.setTransactionId(map.get("transaction_id").toString());
                    or.setStatus(RefundEnum.success.getVal());
                    or.setModifytime(new Date());
                    or.setModifier(ObjectUtil.getUid());
                    or.updateById();

                    OrderGoods nog = new OrderGoods();
                    nog.setStatus(StatusEnum.cancel.getVal());
                    nog.setOid(order.getId());
                    orderGoodsService.update(nog, new EntityWrapper<OrderGoods>().eq("oid", order.getId()));
                } else {
                    json.setCode(5);
                    json.setMsg(map.containsKey("msg") ? map.get("msg").toString() : "退款失败");
                }
            }
        }

        return json;
    }

    @RequestMapping("/admin/order/modify")
    public String update(Order bean) {
        bean.setModifytime(new Date());
        bean.setModifier(ObjectUtil.getUid());
        boolean isSuccc = orderService.updateById(bean);
        if (isSuccc) {
            return "redirect:index";
        }
        return "error";
    }

    @RequestMapping("/admin/order/goodsfix")
    public String goodsfix() {

        List<Goods> goods = goodsService.selectList(new EntityWrapper<Goods>().setSqlSelect("id,info,name")
                .eq("mpid", 1).or().eq("mpid", 22));
        for (Goods item : goods) {
            if (Strings.isNullOrEmpty(item.getInfo())) continue;
            Document doc = Jsoup.parse(item.getInfo());
            Element content = doc.body();
            Elements links = content.getElementsByTag("img");

            StringBuilder sb = new StringBuilder();
            for (Element link : links) {
                sb.append(link.attr("src") + ";");
            }
            item.setInfo(sb.toString());
            item.updateById();
        }

        return "OK";
    }

}

